import { Injectable } from '@angular/core';
import 'reflect-metadata';
import {
    HttpEvent,
    HttpHandler,
    HttpHeaderResponse,
    HttpInterceptor,
    HttpProgressEvent,
    HttpRequest,
    HttpResponse,
    HttpSentEvent,
    HttpUserEvent
} from '@angular/common/http';
import { Observable, Subject, throwError, timeout } from 'rxjs';
import { NzMessageService } from 'ng-zorro-antd/message';
import { catchError, delay, takeUntil, tap } from 'rxjs/operators';
import { ConfigModule } from '../config.module';
import { environment } from '../../environments/environment';
import { Router } from '@angular/router';
import { NzModalService } from 'ng-zorro-antd/modal';
import { WebStorageService } from './webStorage.service';
import {NO_AUTH_METADATA_KEY} from "../decorator/no-auth.decorator";
import {AuthService} from "./auth.service";
import {UserService} from "../pages/system-setting/user/service/user.service";

/**
 * 拦截器
 */
@Injectable({
    providedIn: 'root'
})
export class InterceptorService implements HttpInterceptor {
    pendingHttpRequests$: Subject<any> = new Subject<void>();
    authHeaderProperty = 'Authorization';
    isConfirmShown: boolean;
    constructor(
        private _nzMessageService: NzMessageService,
        private _config: ConfigModule,
        private _router: Router,
        private _nzModalService: NzModalService,
        private webStorageService: WebStorageService
    ) {
    }

    private getAllNoAuthMethods(): Map<string, string> {
        const services = [
            AuthService,
            UserService
            // 添加其他需要检查的服务
        ];

        const noAuthMethods = new Map<string, string>();

        for (const service of services) {
            const methods = Object.getOwnPropertyNames(service.prototype)
                .filter(prop => typeof (service.prototype as any)[prop] === 'function');

            for (const methodName of methods) {
                const methodDescriptor = Object.getOwnPropertyDescriptor(service.prototype, methodName);
                if (methodDescriptor && methodDescriptor.value) {
                    const hasNoAuth = Reflect.getMetadata(NO_AUTH_METADATA_KEY, service.prototype, methodName);
                    if (hasNoAuth) {
                        const methodPath = this.getMethodPath(methodDescriptor.value);
                        if (methodPath) {
                            noAuthMethods.set(methodName, methodPath);
                        }
                    }
                }
            }
        }

        return noAuthMethods;
    }
    private getMethodPath(method: Function): string | undefined {
        // 这里可以根据实际情况解析方法路径
        // 例如，如果方法路径存储在某个元数据中
        // 这里假设方法路径存储在某个元数据中
        return Reflect.getMetadata('path', method);
    }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        //获取token
        const authToken = localStorage.getItem('token');

        // 统一加上服务端前缀
        let url = req.url;
        const host = this.webStorageService.getHost();
        if (host!=null){
            url = url.replace(environment.baseUrl, host);
        }
        let authReq = req.clone({
            url
        });

        const method = req.method.toLowerCase();

        // 获取所有带有 @NoAuth 装饰器的方法
        const noAuthMethods = this.getAllNoAuthMethods();

        // 查找与请求 URL 和方法匹配的服务方法
        let isNoAuth = false;
        for (const [serviceMethod, serviceUrl] of noAuthMethods.entries()) {
            if (url.endsWith(serviceUrl) && method === serviceMethod.toLowerCase()) {
                isNoAuth = true;
                break;
            }
        }

        // 检查是否需要添加 token
        if (authToken !== null && !isNoAuth){
            if (url.endsWith("/system/user/profile/avatar")){
                authReq =  authReq.clone({
                    url: authReq.url,
                    headers: req.headers.set(this.authHeaderProperty, 'Bearer '+authToken)
                });
            }else {
                authReq =  authReq.clone({
                    url: authReq.url,
                    headers: req.headers.set(this.authHeaderProperty, authToken)
                });
            }
        }

        return next.handle(authReq).pipe(
            delay(200),
            takeUntil(this.pendingHttpRequests$.asObservable()),
            timeout(60000),
            tap(
                (event) => {
                    this.webCodeOption(authReq.url, event);
                    // this.apmsCodeOption(authReq.url, event);
                },
                (error) => {
                    // this.errorOption(error);
                }
            ),
            catchError((error) => {
                if (error instanceof ErrorEvent) {
                    // 客户端错误
                    this._nzMessageService.create('error', '客户端错误: ' + error.message);
                } else if (error.name === 'TimeoutError') {
                    // 超时错误
                    this._nzMessageService.create('error', '请求超时，请检查网络连接或稍后再试！');
                } else {
                    // 服务器错误
                    this.errorOption(error);
                }
                return throwError(error);
            })
        );
    }

    webCodeOption(url: string, event: HttpSentEvent | HttpHeaderResponse | HttpResponse<any> | HttpProgressEvent | HttpUserEvent<any>){
        if (url.startsWith(environment.baseUrl)){
            if (event instanceof HttpResponse) {
                if (event.body.code === 401) {
                    // this.pendingHttpRequests$.next();
                    if (!this.isConfirmShown){
                        this._nzModalService.confirm({
                            nzTitle: '<i>温馨提示</i>',
                            nzContent: `<b>登录凭证已过期，点击确定重新登录！</b>`,
                            nzCancelText: null,
                            nzCloseIcon: null,
                            nzWrapClassName: 'vertical-center-modal',
                            nzOnOk: () => {
                                localStorage.clear();
                                this.isConfirmShown = false;
                                this._router.navigateByUrl('/login').finally();
                            }
                        });
                        this.isConfirmShown = true;
                    }
                } else if (event.body.code === 401) {
                    localStorage.clear();
                    this._router.navigateByUrl('/login');
                }
                else if (event.body.code !== 200 && event.body.msg !== undefined) {
                    this._nzMessageService.create('error', event.body.msg);
                }

                if (event.body.code === 200){
                    //统一加上判断值
                    event.body.success = true;
                }
            }
        }
    }

    /**
     * 请求错误返回值处理
     * @param error
     */
    errorOption(error: any){
        switch (error.status) {
            case 500:
                this._nzMessageService.create('error', '请求失败，请重试！');
                break;
            case 405:
                this._nzMessageService.create('error', '请求方法错误！');
                break;
            case 400:
                this._nzMessageService.create('error', 'Bad Request！');
                break;
            case 404:
                this._nzMessageService.create('error', `找不到接口：${error.error.path}！`);
                break;
            default:
                this._nzMessageService.create('error', error.statusText);
        }
    }
}
